#pragma once

//some tools for matrix

#include "zMatrix.hpp"
namespace zzz{
template<typename T,class Major>
const zMatrix<T,zColMajor> Temp(const zMatrixBaseR<T,Major> &mat)
{
  zMatrix<T,zColMajor> v(mat);
  return v;
}

template<typename T,class Major>
class zTransMatrix : public zMatrixBaseR<T,Major>
{
public:
  explicit zTransMatrix(const zMatrixBaseR<T,Major>& mat)
  :zMatrixBaseR<T,Major>(mat.cols_,mat.rows_),Mat_(mat){}
  using zMatrixBaseR<T,Major>::operator();
  const T operator()(zuint r, zuint c) const
  {
    CheckRange(r, c);
    return Mat_(c,r);
  }
public:
  const zMatrixBaseR<T,Major> &Mat_;
};
template<typename T,class Major>
const zTransMatrix<T,Major> Trans(const zMatrixBaseR<T,Major>& mat)
{return zTransMatrix<T,Major>(mat);}

template<typename T,class Major>
T Sum(const zMatrixBaseR<T,Major> &mat)
{
  T sum=0;
  for (zuint r=0; r<mat.rows_; r++) for (zuint c=0; c<mat.cols_; c++)
    sum+=mat(r,c);
  return sum;
}

template<typename T,class Major>
T Dot(const zMatrixBaseR<T,Major> &mat1, const zMatrixBaseR<T,Major> &mat2)
{
  T sum=Sum(DotTimes(mat1,mat2));
  return sum;
}


template<typename T,class Major>
T Norm(const zMatrixBaseR<T,Major> &mat)
{
  T sqrsum=Dot(mat,mat);
  return Sqrt<T>(sqrsum);
}
}
